package org.wattdepot.cli.command;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.wattdepot.cli.processor.CommandLineInterface;
import org.wattdepot.client.BadXmlException;
import org.wattdepot.client.MiscClientException;
import org.wattdepot.client.NotAuthorizedException;
import org.wattdepot.client.ResourceNotFoundException;
import org.wattdepot.resource.property.jaxb.Properties;
import org.wattdepot.resource.source.jaxb.Source;

/**
 * FuelTypes - gets types of fuel.
 * 
 * @author Remy Baumgarten
 * @author Kevin Chiogioji
 * 
 */
public class FuelTypes extends CommandLineInterface implements WattDepotCliCommand {

  /**
   * Concerts URL to Source.
   * 
   * @param url - full url
   * @return - source without the addons
   */
  public String urlToSource(String url) {
    return url.substring(url.lastIndexOf('/') + 1, url.length());
  }

  /**
   * Converts FuelType HashMap to a String.
   * 
   * Takes a HashMap and iterates through to print out which nonvirtual sources use a specific type
   * of energy.
   * 
   * @param fuelMap - hashmap
   * @return - string ready to dispatch
   */
  public String hashToString(Map<String, List<String>> fuelMap) {
    StringBuffer buff = new StringBuffer(255);
    buff.append(cr).append("LSFO:  ");
    for (String item : fuelMap.get("LSFO")) {
      buff.append(item).append(' ');
    }
    buff.append(cr).append("Waste:  ");
    for (String item : fuelMap.get("waste")) {
      buff.append(item).append(' ');
    }
    buff.append(cr).append("Coal:  ");
    for (String item : fuelMap.get("coal")) {
      buff.append(item).append(' ');
    }
    buff.append(cr);
    return buff.toString();
  }

  /**
   * Gets the fueltypes of the sources.
   * 
   * @param source - virtual
   * @return fueltype - string
   * @throws BadXmlException -
   * @throws ResourceNotFoundException -
   * @throws NotAuthorizedException -
   * @throws MiscClientException -
   */
  public String getFuelType(Source source) throws MiscClientException, NotAuthorizedException,
      ResourceNotFoundException, BadXmlException {
    // HashMap for Energy Type to List of Sources
    HashMap<String, List<String>> fuelMap = new HashMap<String, List<String>>();
    // Energy Type ArrayLists that hold sources
    List<String> waste = new ArrayList<String>();
    List<String> LSFO = new ArrayList<String>();
    List<String> coal = new ArrayList<String>();
    if (source.isSetSubSources()) {
      // Get all raw URL's to a String List
      List<String> urlList = source.getSubSources().getHref();
      String sub, fuelType;
      // Loop through urlList, increasing list size with new subsources if source is virtual
      for (int i = 0; i < urlList.size(); i++) {
        sub = urlToSource(urlList.get(i));
        // source is virtual, get subsources and add to list
        if (client.getSource(sub).isVirtual()) {
          Source current = client.getSource(sub);
          urlList.addAll(current.getSubSources().getHref());
          continue;
        }
        // get fueltype of nonvirtual source and source name to arraylist
        fuelType = client.getSource(sub).getProperty("fuelType");
        if ("LSFO".equals(fuelType)) {
          LSFO.add(sub);
        }
        else if ("waste".equals(fuelType)) {
          waste.add(sub);
        }
        else if ("coal".equals(fuelType)) {
          coal.add(sub);
        }
      }
      // place play all arraylists of sources into HashMap
      fuelMap.put("LSFO", LSFO);
      fuelMap.put("coal", coal);
      fuelMap.put("waste", waste);
    }
    // Turn HashMap into a pretty string
    return hashToString(fuelMap);
  }

  /**
   * Gets type of fuel.
   * 
   * @param args -
   * @return -
   */
  @Override
  public String doCommand(List<String> args) {
    try {
      Source source = client.getSource(args.get(0));
      if (source.isVirtual()) {
        // recurse through all subsources and append fueltypes to buffer
        return getFuelType(source);
      }
      Properties prop = source.getProperties();
      return source.getName() + ": " + prop.getProperty("fuelType");
    }
    catch (IndexOutOfBoundsException e) {
      return commandError;
    }
    catch (NotAuthorizedException e) {
      return error401;
    }
    catch (ResourceNotFoundException e) {
      return error404;
    }
    catch (BadXmlException e) {
      return errorXML;
    }
    catch (MiscClientException e) {
      return errorClient;
    }
  }
}
